home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 June: Reference Library / Dev.CD Jun 95 / Dev.CD Jun 95.toast / Technical Documentation / Mac Tech Notes (DocViewer) / PR • Printing / PR10-Printing Loop / PR10-Printing Loop
Encoding:
Text File  |  1994-07-24  |  77.2 KB  |  400 lines  |  [ONLN/HLX2]

  1. PR 10 - A Printing Loop That Cares…
  2. Printing    ernigan & Pete “Luke” Alexander    October 1990
  3. This Technical Note discusses opening and closing the Printing Manager with calls to _PrOpen and _PrClose as well as how to handle errors at print time.
  4. Changes since October 1990:  Added code in both versions to handle printing documents larger than 128 pages.
  5. Introduction
  6. At one time, Apple recommended that developers call _PrOpen at the beginning of their application and _PrClose at the end, before returning to the Finder.  This recommendation was in the ancient past when an application only had to deal with a single printer driver.
  7. As more printer drivers became available, it became important for an application to consider the presence of other applications and how opening and closing the printer driver affected them.  The user could open the Chooser at any time and change the current printer driver without the current application’s knowledge.  If an application followed the old philosophy and a user changed the current printer driver while running the application, the next time the user attempted to print, the wrong driver would be open, the Printing Manager would not be able to find the necessary resources, and the user would get an error.
  8. The Current Recommendation
  9. DTS currently recommends that applications open and close the printer driver each time the application uses the Printing Manager.
  10. MPW Pascal
  11. *------ PrintStuff ----------------------------------------------------------------*}
  12. {**
  13.  **    PrintStuff will call all of the necessary Print Manager calls to print
  14.  **    a document.  It checks PrError() after each Print Manager call.  If an
  15.  **    error is found, all of the Print Manager open calls (i.e., PrOpen,
  16.  **    PrOpenDoc...) will have a corresponding close call before the error
  17.  **    is posted to the user.  You want to use this approach to make sure the
  18.  **    Print Manager closes properly and all temporary memory is released.
  19.  **}
  20. PROCEDURE PrintStuff;
  21. VAR
  22.   copies,
  23.   firstPage,
  24.   lastPage,
  25.   loop,
  26.   numberOfCopies,
  27.   pageNumber,
  28.   printmgrsResFile,
  29.   realNumberOfPagesInDoc  : Integer;
  30.   PrintError              : LongInt;
  31.   oldPort                 : GrafPtr;
  32.   thePrRecHdl             : THPrint;
  33.   thePrPort               : TPPrPort;
  34.   theStatus               : TPrStatus;
  35. BEGIN
  36.   GetPort(oldPort);
  37.   {**
  38.       UnLoadTheWorld will swap out ALL unneeded code segments and data that are NOT
  39.       required
  40.       during print time. Your print code must be a separate code segment.
  41.   **}
  42.   UnLoadTheWorld;
  43.   thePrRecHdl := THPrint(NewHandle(SIZEOF(TPrint)));
  44.   IF (MemError = noErr) AND (thePrRecHdl <> NIL) THEN
  45.     BEGIN
  46.       PrOpen;
  47.         IF (PrError = noErr) THEN
  48.           BEGIN
  49.             {**
  50.                 Save the current resource file (i.e. the printer driver's)
  51.                 so the driver will not lose its resources upon return from
  52.                 the pIdleProc.
  53.              **}
  54.             printmgrsResFile := CurResFile;
  55.             PrintDefault(thePrRecHdl);
  56.             IF (PrError = noErr) THEN
  57.               BEGIN
  58.                 IF (PrStlDialog(thePrRecHdl)) THEN
  59.                   BEGIN
  60.                     {**
  61.                         DetermineNumberOfPagesinDoc determines the number of
  62.                         pages contained in the document by comparing the size of
  63.                         the document with rPage from the TPrInfo record (IM II-150).
  64.                         It returns the number of pages required to print the
  65.                         document for the currently selected printer.
  66.                      **}
  67.                     realNumberOfPagesinDoc := DetermineNumberOfPagesinDoc
  68.                                                   (thePrRecHdl^^.prInfo.rPage);
  69.                     IF (PrJobDialog(thePrRecHdl)) THEN 
  70.                       BEGIN
  71.                         {**
  72.                             Get the number of copies of the document that the
  73.                             user wants printed from iCopies of the TPrJob record
  74.                             (IM II-151).
  75.                          **}
  76.                         numberOfCopies := thePrRecHdl^^.prJob.iCopies;
  77.                         {**
  78.                             Get the first and last pages of the document that
  79.                             were requested to be printed by the user from iFstPage
  80.                             and iLastPage from the TPrJob record (IM II-151).
  81.                          **}
  82.                         firstPage := thePrRecHdl^^.prJob.iFstPage;
  83.                         lastPage := thePrRecHdl^^.prJob.iLstPage;
  84.                         {**
  85.                             Print "all" pages in the print loop
  86.                          **}
  87.                         thePrRecHdl^^.prJob.iFstPage := 1;
  88.                         thePrRecHdl^^.prJob.iLstPage := 9999;
  89.                         {**
  90.                             Determine the "real" number of pages contained in
  91.                             the document.  Without this test, you would print
  92.                             9999 pages.
  93.                          **}
  94.                         IF (realNumberOfPagesinDoc < lastPage) THEN
  95.                           lastPage := realNumberOfPagesinDoc;
  96.                         PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));
  97.                         
  98.                         {**
  99.                             Print the number of copies of document requested by the
  100.                   user
  101.                             from the Print Job Dialog.
  102.                          **}
  103.                         For copies := 1 To numberOfCopies Do
  104.                           BEGIN
  105.                             {**
  106.                                 Install a pointer to your pIdle proc in my print record.
  107.                              **}
  108.                              thePrRecHdl^^.prJob.pIdleProc := @checkMyPrintDialogButton;
  109.                             {**
  110.                                 Restore the resource file to the printer driver's.
  111.                              **}
  112.                             UseResFile(printmgrsResFile);
  113.                             thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  114.                             IF (PrError = noErr) THEN
  115.                               BEGIN
  116.                                 {**
  117.                                     Print the range of pages of the document requested
  118.                                     by the user from the Print Job Dialog.
  119.                                  **}
  120.                                 pageNumber := firstPage;
  121.                                 WHILE ((pageNumber <= lastPage) AND (PrError = noErr)) DO
  122.                                   BEGIN
  123.                       
  124.                     { **
  125.                     If we've crossed a 128-page boundary,
  126.                     close the current print file, send it
  127.                     to the printer if necessary, and open a
  128.                     new document.
  129.                     ** }
  130.                       
  131.                     IF (pageNumber - firstPage) MOD iPFMaxPgs = 0 THEN
  132.                                       BEGIN
  133.                                         IF pageNumber <> firstPage THEN
  134.                                           BEGIN
  135.                                             PrCloseDoc(thePrPort);
  136.                                             IF (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop)
  137.                                               AND (PrError = noErr) THEN
  138.                                               PrPicFile(thePrRecHdl, NIL,NIL, NIL, theStatus);
  139.                                             thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);
  140.                                           END;
  141.                                         END;
  142.                       PrOpenPage(thePrPort, NIL);
  143.                                       IF (PrError = noErr) THEN
  144.                                         BEGIN
  145.                                           {**
  146.                                               rPage (IM II-150) is the printable
  147.                                               area for the currently selected printer.
  148.                                               By passing the current enables your app to use
  149.                           the same routine to draw to the screen and the
  150.                           printer's GrafPort.
  151.                                            **}
  152.                                           DrawStuff (thePrRecHdl^^.prInfo.rPage, 
  153.                                                      GrafPtr (thePrPort), 
  154.                                                      pageNumber);
  155.                                         END;
  156.                                       PrClosePage(thePrPort);
  157.                                       pageNumber := pageNumber + 1;
  158.                                   END;  {**  End pagenumber loop  **}
  159.                               END;
  160.                             PrCloseDoc(thePrPort);
  161.                           END;  {**  End copies loop  **}
  162.                           {**
  163.                               The printing job is being canceled by the request of
  164.                               the user from the Print Style Dialog or the Print Job
  165.                               Dialog.  PrError will be set to iPrAbort to tell the
  166.                               Print Manager to abort the current printing job.
  167.                            **}
  168.                       END
  169.                         ELSE
  170.                       PrSetError(iPrAbort);   {**  Cancel from the job dialog  **}
  171.                   END
  172.                     ELSE
  173.                   PrSetError(iPrAbort);   {**  Cancel from the style dialog  **}
  174.               END;
  175.           END;
  176.     IF (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) THEN
  177.       PrPicFile(thePrRecHdl, NIL, NIL, NIL, theStatus);
  178.     {**
  179.         Grab the printing error -- once you close the Printing Manager, PrError doesn't return
  180.         a valid result anymore.
  181.      **}
  182.     PrintError := PrError;
  183.     PrClose;
  184.     {**
  185.         You do not want to report any printing errors until you have fallen
  186.         through the printing loop. This will make sure that ALL of the Print
  187.         Manager's open calls have their corresponding close calls, thereby
  188.         enabling the Print Manager to close properly and that all temporary
  189.         memory allocations are released.
  190.      **}
  191.     IF (PrintError <> noErr) THEN
  192.       PostPrintingErrors (PrintError);
  193.     END;
  194.   IF (thePrRecHdl <> NIL) THEN 
  195.     DisposHandle(Handle (thePrRecHdl));
  196.   IF (PrintingStatusDialog <> NIL) THEN 
  197.     DisposDialog(PrintingStatusDialog);
  198.   SetPort(oldPort);
  199. END;  {**  PrintStuff  **}
  200. MPW C
  201. /*------ PrintStuff ----------------------------------------------------------------*/
  202.  **
  203.  **    PrintStuff will call all of the necessary Print Manager calls to print
  204.  **    a document. It checks PrError() after each Print Manager call. If an error
  205.  **    is found, all of the Print Manager open calls (i.e., PrOpen, PrOpenDoc...)
  206.  **    will have a corresponding close call before the error is posted to the user.
  207.  **    You want to use this approach to make sure the Print Manager closes properly
  208.  **    and all temporary memory is released.
  209.  **/
  210. void PrintStuff ()
  211. {
  212.   GrafPtr      oldPort;
  213.   short        copies,
  214.                firstPage,
  215.                lastPage,
  216.                numberOfCopies,
  217.                printmgrsResFile,
  218.                realNumberOfPagesinDoc,
  219.                pageNumber,
  220.                PrintError;
  221.   THPrint      thePrRecHdl;
  222.   TPPrPort     thePrPort;
  223.   TPrStatus    theStatus;
  224.   GetPort(&oldPort);
  225.  /**
  226.      UnLoadTheWorld will swap out ALL unneeded code segments and data that
  227.      are NOT required during print time. Your print code must be a separate
  228.      code segment.
  229.   **/
  230.   UnLoadTheWorld ();
  231.   thePrRecHdl = (THPrint)  NewHandle (sizeof (TPrint));
  232.  /**
  233.      Check to make sure that the memory manager did not produce an error
  234.      when it allocated the print record handle and make sure it did not pass
  235.      back a nil handle.
  236.   **/
  237.   if (MemError() == noErr && thePrRecHdl != nil)
  238.     {
  239.       PrOpen();
  240.       if (PrError() == noErr)
  241.         {
  242.          /**
  243.               Save the current resource file (i.e. the printer driver's) so
  244.               the driver will not lose its resources upon return from the pIdleProc.
  245.           **/
  246.           printmgrsResFile = CurResFile();
  247.           PrintDefault(thePrRecHdl);
  248.           if (PrError() == noErr)
  249.             {
  250.               if (PrStlDialog(thePrRecHdl))
  251.                 {
  252.                  /**
  253.                      DetermineNumberOfPagesinDoc determines the number of pages
  254.                      contained in the document by comparing the size of the document
  255.                      with rPage from the TPrInfo record (IM II-150). It returns the
  256.                      number of pages required to print the document for the                          currently selected printer.
  257.                   **/
  258.                   realNumberOfPagesinDoc = DetermineNumberOfPagesinDoc
  259.                                              ((**thePrRecHdl).prInfo.rPage);
  260.                   if (PrJobDialog(thePrRecHdl)) 
  261.                     {
  262.                      /**
  263.                           Get the number of copies of the document that the user 
  264.                           wants printed from iCopies of the TPrJob record (IM II-151).
  265.                       **/
  266.                       numberOfCopies = (**thePrRecHdl).prJob.iCopies;
  267.                        /**
  268.                            Get the first and last pages of the document that
  269.                            were requested to be printed by the user from iFstPage
  270.                            and iLastPage from the TPrJob record (IM II-151).
  271.                         **/
  272.                       firstPage = (**thePrRecHdl).prJob.iFstPage;
  273.                       lastPage = (**thePrRecHdl).prJob.iLstPage;
  274.                        /**
  275.                            Print "all" pages in the print loop
  276.                         **/
  277.                       (**thePrRecHdl).prJob.iFstPage = 1;
  278.                       (**thePrRecHdl).prJob.iLstPage = 9999;
  279.                        /**
  280.                            Determine the "real" number of pages contained in the                        document. Without this test, you would print 9999 pages.
  281.                         **/
  282.                       if (realNumberOfPagesinDoc < lastPage) 
  283.                         lastPage = realNumberOfPagesinDoc;
  284.                       PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);
  285.                        /**
  286.                            Print the number of copies of the document
  287.                            requested by the user from the Print Job Dialog.
  288.                         **/
  289.                       for (copies = 1; copies <= numberOfCopies; copies++)
  290.                         {
  291.                          /**
  292.                              Install a pointer to your pIdle proc in my print record.
  293.                           **/
  294.                           (**thePrRecHdl).prJob.pIdleProc = checkMyPrintDialogButton;
  295.                          /**
  296.                              Restore the resource file to the printer driver's.
  297.                           **/
  298.                           UseResFile(printmgrsResFile);
  299.                           thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);
  300.                           if (PrError() == noErr)
  301.                             {
  302.                              /**
  303.                                  Print the range of pages of the document 
  304.                                  requested by the user from the Print Job Dialog.
  305.                               **/
  306.                               pageNumber = firstPage;
  307.                               while (pageNumber <= lastPage && PrError() == noErr)
  308.                                 {
  309.                                   
  310.                      /**
  311.                        If we've crossed a 128-page boundary,
  312.                        close the current print file, send it
  313.                        to the printer if necessary, and open a
  314.                        new document.
  315.                      **/
  316.                      
  317.                      if ((pageNumber - firstPage) % iPFMaxPgs == 0)
  318.                        {
  319.                          if (pageNumber != firstPage)
  320.                            {
  321.                              PrCloseDoc(thePrPort);
  322.                              if (((**thePrRecHdl).prJob.bJDocLoop ==
  323.                                              bSpoolLoop) && (PrError() == noErr))
  324.                                              PrPicFile(thePrRecHdl, nil, nil, nil,
  325.                                                        &theStatus);
  326.                              thePrPort = PrOpenDoc(thePrRecHdl, nil,
  327.                                                                 nil);
  328.                                          }
  329.                                      }    
  330.                      PrOpenPage(thePrPort, nil);
  331.                                   if (PrError() == noErr) 
  332.                                     {
  333.                                      /**
  334.                                          rPage (IM II-150) is the printable area
  335.                                          for the currently selected printer. By                          passing the current port to the draw                              routine, enables your app to use the same                          routine to draw to the screen and the                          printer's GrafPort.
  336.                                       **/
  337.                                       DrawStuff ((**thePrRecHdl).prInfo.rPage, 
  338.                                                  (GrafPtr) thePrPort, pageNumber);
  339.                                     }
  340.                                   PrClosePage(thePrPort);
  341.                                   pageNumber++;
  342.                                 }  /**  End pageNumber loop  **/
  343.                             }
  344.                           PrCloseDoc(thePrPort);
  345.                         } /**  End copies loop  **/
  346.                     }
  347.                    /**
  348.                        The printing job is being canceled by the request of the
  349.                        user from the Print Style Dialog or the Print Job Dialog.
  350.                        PrError will be set to PrAbort to tell the Print Manager to
  351.                        abort the current printing job.
  352.                     **/
  353.                   else
  354.                     PrSetError (iPrAbort);   /**  cancel from the job dialog  **/
  355.                 }
  356.               else
  357.                 PrSetError (iPrAbort);   /**  cancel from the style dialog  **/ 
  358.             }
  359.         }
  360.       if (((**thePrRecHdl).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr))
  361.         PrPicFile(thePrRecHdl, nil, nil, nil, &theStatus);
  362.        /**
  363.            Grab the printing error -- once you close the Printing Manager, PrError doesn't
  364.        returna valid result anymore. 
  365.        **/
  366.       PrintError = PrError();
  367.       PrClose();
  368.        /**
  369.            You do not want to report any printing errors until you have fallen
  370.            through the printing loop. This will make sure that ALL of the Print
  371.            Manager's open calls have their corresponding close calls, thereby
  372.            enabling the Print Manager to close properly and that all temporary
  373.            memory allocations are released.
  374.         **/
  375.       if (PrintError != noErr) 
  376.         PostPrintingErrors (PrintError);
  377.     }
  378.   if (thePrRecHdl != nil)
  379.     DisposHandle((Handle) thePrRecHdl);
  380.   if (PrintingStatusDialog != nil)
  381.     DisposDialog(PrintingStatusDialog);
  382.   SetPort(oldPort);
  383. }  /** PrintStuff **/
  384. Checking And Handling Printing Errors
  385. An application should always check for error conditions while printing by calling PrError.  PrError returns errors from the Printing Manager (and some AppleTalk and OS errors) that occur during printing.
  386. As the example code demonstrates, an application should call PrError after each call to a Printing Manager function or procedure.  By consistently checking PrError after each call, the application is able to catch any errors created at print time and report them to a user via a dialog box in a clean and graceful manner.
  387. The following section outlines some general error-handling guidelines.
  388. •    You should avoid calling PrError within your pIdle procedure; errors that occur while it is executing are usually temporary and serve only as internal flags for communication within the printer driver—they are not intended for the application.  If you absolutely must call PrError within your idle procedure, and an error occurs, never abort printing within the idle procedure itself.  Wait until the last called printing procedure returns, then check to see if the error still remains.  Attempting to abort printing within an idle procedure is a guarantee of certain death.
  389. •    Upon detecting an error after the completion of a printing routine, stop drawing at that point, and proceed to the next procedure to close any previously made open calls.  For example, if you detect an error after calling PrOpenDoc, skip to the next PrCloseDoc.  Or, if you get an error after calling PrOpenPage, skip to the next PrClosePage and PrCloseDoc.  Remember that if you have called PrOpen, then you must call the corresponding PrClose to ensure that printing closes properly and all temporary memory allocations are released and returned to the heap.
  390. •    Do not display any alert or dialog boxes to report an error until the end of the printing loop.  Once at the end, check for the error again; if there is no error assume that printing completed normally.  If the error is still present, then you can alert the user.
  391.     This technique is important for two reasons.  First, if you display a dialog box in the middle of the printing loop, it could cause errors that can terminate an otherwise normal job.  For example, if the printer is an AppleTalk printer, the connection can be terminated abnormally since the driver would be unable to respond to AppleTalk requests received from the printer while the dialog box was waiting for input from the user.  If the printer does not hear from the Macintosh with a short period of time (e.g., 30 seconds), it times out, assuming that the Macintosh is no longer there, which results in a prematurely broken connection causing another error to which the application must respond.
  392.     In addition, the driver may have already displayed its own dialog box in response to an error.  In this instance, the driver posts an error to let the application know that something went wrong and it should abort printing.  For example, when the LaserWriter driver detects that the Laser Prep version which has been downloaded to the LaserWriter is different than that with which the user is trying to print, it displays the appropriate dialog box informing the user of the situation and giving him the option of reinitializing the printer.  If the user chooses to cancel printing, the driver posts an error to let the application know that it needs to abort, but since the driver has already taken care of the error by displaying a dialog box, the error is reset to zero before the printing loop is complete.  The application should check for the error again at the end of the printing loop, and if it still indicates an error, the application can then display the appropriate dialog box.
  393. •    If using PrGeneral, be prepared to receive the following errors:  NoSuchRsl, OpNotImpl, and resNotFound.  In all three cases, the application should be prepared to continue to print without using the features of that particular opcode.
  394.     However, in the case of the resNotFound error, it means the current printer driver does not support PrGeneral.  This lack of support should not be a problem for an application, but it needs to be prepared to deal with this error.  If you receive a resNotFound error from PrError, clear the error with a call to PrSetError(0); otherwise, PrError might still contain this error the next time you check it, which would prevent your application from printing.
  395. Canceling or Pausing the Printing Process
  396. If you install a procedure for handling requests to cancel printing, with an option to pause the printing process, beware of timeout problems when printing to the LaserWriter.  Communication between the Macintosh and the LaserWriter must be maintained to prevent a job or a wait timeout.  If there is no communication for a period of time (over two minutes), the printer times out and the print job terminates due to a wait  timeout.  Or, if the print job requires more than three minutes to print, the print job terminates due to a job timeout.  Since, there is no good method to determine to what type of printer an application is printing, it is probably a good idea to document the possibility of a LaserWriter timing out for a user who chooses to select “pause” for over two minutes.
  397. Error Messages Created In Print Land…
  398. The Printing Manager reports the error messages covered in this section.  If an error that does not belong to the Printing Manager occurs, the Printing Manager puts it into low memory, where it can be retrieved with a call to PrError, and terminates the printing loop, if necessary.  As already documented, if you encounter an error in the middle of a printing loop, do not jump out; fall through the loop and let the Printing Manager terminate properly.
  399. Error Code    Constant    Description
  400.     0    noErr    No error
  401.     128    iPrAbort    Abort the printing process 
  402.             (Command-period)
  403.     -1    iPrSavePFil    Problem saving print file
  404.     -17    controlErr    Unimplemented Control call
  405.     -27    iIOAbort    I/O problems
  406.     -108    iMemFullErr    Not enough heap space
  407. The following errors are specific to the LaserWriter family:
  408.     -4101        Printer not found or closed
  409.     -4100        Connection just closed
  410.     -4099        Write request too big
  411.     -4098        Request already active
  412.     -4097        Bad connection refnum
  413.     -4096        No free Connect Control Blocks (CCBs) available
  414.     -8133        PostScript error occurred during transmission of data to printer.  Most often caused by a bug in the PostScript code being downloaded.
  415.     -8132        Timeout occurred.  This error is returned when no data has been sent to the printer for two minutes.  Usually caused by extremely long imaging time.
  416.     -8131        Printer not responding:  it may have been turned “off.”  This error occurs if a user turns off the LaserWriter in the middle of a print job.
  417. The following errors are specific to PrGeneral:
  418.     1    NoSuchRsl    Requested resolution is not supported
  419.     2    OpNotImpl    Requested PrGeneral opcode not implemented in the current printer driver.
  420.     -192    resNotfound    The current printer driver does not support PrGeneral.
  421. The most common error encountered is -4101, which is generated if no LaserWriter is selected.  Since this error is so common, it is a good idea to display a dialog box requesting the user to select a printer from the Chooser when this error is encountered.
  422. Further Reference:
  423. •    Inside Macintosh, Volume II-145 & V-410, The Printing Manager
  424. •    Technical Note M.IM.DevIndPrinting —
  425.          Device-Independent Printing
  426. •    d e v e l o p, July 1990, Issue 3, “Meet PrGeneral”
  427. ◊#ˇ ˇˇˇˇ#◊†Ç 
  428. 6Zà#
  429.     0Ià:µú9"Ç    ˇˇˇˇˇˇˇˇ#†ƒ°d
  430. ONLNf˛†å°d1drw2…-·_ġˇˇˇˇˇè°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˙ó@†ò,Times
  431. .R…R…+]INew Technical Notes†ô°ddrw2:°„†ó°d1drw2eÙġˇˇˇˇˇP°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚ÄE¿†ò
  432. (ÇïDeveloper Support†ô°ddrw2:°„†ó°d`drw2-ÔˇˇˇˇˇˇKÔ- Z  mmZ°d1drw2 ¿˙ÈˇˇˇˇˇˇK°ñ x°ddrw2:°ddrw2:$°d4drw2:0°öˇÙĆò
  433. 0(\Ô†ô°ddrw2:°„†ó°d1drw2ÔÊ˙ˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:    °öˇ˝Ä†ò
  434.     +&    ®†ô°ddrw2:°„†ó°d1drw2Â-¯yˇˇˇˇˇˇ°ñ x°ddrw2:°ddrw2:$°d4drw2:°öˇ˚Ä%†ò
  435. (a\    Macintosh†ô°ddrw2:°„†ó†ç°ddrw2D†É
  436. IR.°dONLNdu<ày(¢Z#PR 10 - A Printing Loop That Cares…
  437. °dONLNd$á<ìb*
  438. Printing°dONLNd-áÑì")Hernigan & Pete “Luke” Alexander°dONLNdMáæì˛(Ø‹ October 1990°dONLNdZü<´W(«ZThis °dONLNd_üW´˛)OTechnical Note discusses opening and closing the Printing Manager with calls to,
  439. Courier°dONLNdØ´<∑m(‘Z_PrOpen°dONLNd∂¨m∏Ñ)1 and °dONLNdª´Ñ∑º)_PrClose°dONLNd√¨º∏ë)8/ as well as how to handle errors at print time.°dONLNdÛ∏<ƒ·(‡ZChanges since October 1990:°dONLNd∏·ƒF)•  Added code in both °dONLNd#∏Fƒ˛)e%versions to handle printing documents"◊W °dONLNdIƒ<–•(ÏZlarger than 128 pages."„W  ˚X˚
  440. °dONLNd`È<¯è*( Introduction
  441. °dONLNdm<5*/At one time, Apple recommended that developers °dONLNdú5K)˘call °dONLNd°K|)_PrOpen°dONLNd®|˛)1 at the beginning of their°dONLNd√<à(:Zapplication and °dONLNd”à¿)L_PrClose°dONLNd€¿ñ)8. at the end, before returning to the Finder.  °dONLNd    ñ˛)÷This recommendation°dONLNd<*Ÿ(FZZwas in the ancient past when an application only had to deal with a single printer driver.°dONLNdx6<B∑*QAs more printer drivers became available, it became important for an application °dONLNd…6∑B˛(^’to consider the°dONLNdŸB<Nt(jZ?presence of other applications and how opening and closing the °dONLNdBtN˛(jíprinter driver affected them.°dONLNd7N<Z€(vZ The user could open the Chooser °dONLNdWN€Z˛)ü=at any time and change the current printer driver without the°dONLNdïZ<fÍ(ÇZVcurrent application’s knowledge.  If an application followed the old philosophy and a °dONLNdÎZÍf˛(Çuser°dONLNdf<r (éZ)changed the current printer driver while °dONLNdf r˛)œ/running the application, the next time the user°dONLNdIr<~ö(öZIattempted to print, the wrong driver would be open, the Printing Manager °dONLNdírö~˛(ö∏would not be able to°dONLNdß~<ä_(¶Z>find the necessary resources, and the user would get an error.
  442. °dONLNdÊ¢<±*'The Current Recommendation
  443. °dONLNdΩ<…a*:DTS currently recommends that applications open and close °dONLNd;Ωa…π(Âthe printer driver °dONLNdNΩπ…“)Xeach°dONLNdRΩ“…˛)     time the°dONLNd\…<’Ò(ÒZ&application uses the Printing Manager.°dONLNdÉ·<ÌÉ*
  444. MPW Pascal
  445.     °dONLNdé˘<÷*R*------ PrintStuff ---------------------------------------------------------------°dONLNd‡˘÷€( Ù-°dONLNd·<F(*Z*}°dONLNd‰
  446. <K*
  447. {**°dONLNdË<"K*
  448.  **°dONLNdÏ`"æ)$FPrintStuff will call all of the necessary Print Manager calls to print°dONLNd3!<,K(HZ **°dONLNd7!`,æ)$Fa document.  It checks PrError() after each Print Manager call.  If an°dONLNd~+<6K(RZ **°dONLNdÇ+`6™)$Berror is found, all of the Print Manager open calls (i.e., PrOpen,°dONLNd≈5<@K(\Z **°dONLNd…5`@Ø)$CPrOpenDoc...) will have a corresponding close call before the error°dONLNd
  449. ?<JK(fZ **°dONLNd?`Jæ)$Fis posted to the user.  You want to use this approach to make sure the°dONLNdXI<TK(pZ **°dONLNd\I`TØ)$CPrint Manager closes properly and all temporary memory is released.°dONLNd†S<^P(zZ **}°dONLNd•g<r•*PROCEDURE PrintStuff;°dONLNdª{<ÜK*VAR ∂X∂
  450. *,#PR 10 - A Printing Loop That Cares…(Œˇ1) of 12(‰ZM.PR.PrintLoopˇ°¿Ù%%DSIDICT:_cv
  451. currentdict /bu known {bu}if
  452. userdict /_cv known not{userdict /_cv 30 dict put}if
  453. _cv begin
  454. /bdf{bind def}bind def
  455. currentscreen/cs exch def/ca exch def/cf exch def
  456. /setcmykcolor where{/setcmykcolor get /cvcmyk exch def}{/cvcmyk{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf }ifelse
  457. /ss{//cf //ca //cs setscreen}bdf
  458. /stg{ss setgray}bdf
  459. /strgb{ss setrgbcolor}bdf
  460. /stcmyk{ss cvcmyk}bdf
  461. /min1{dup 0 eq{pop 1}if}bdf
  462. end
  463. currentdict /bn known {bn}if
  464. †øà◊#ˇ ˇˇˇˇ#◊ 
  465. IR,Times
  466. .+6-Macintosh Technical Notes /4/˘,
  467. Courier
  468.     °dONLNd(E*      copies,°dONLNd
  469. '2T*
  470.   firstPage,°dONLNd1<O*
  471.   lastPage,°dONLNd#;F;*
  472.   loop,°dONLNd+EPm*
  473.   numberOfCopies,°dONLNd=OZY*
  474.  
  475.   pageNumber,°dONLNdKYdw*
  476.   printmgrsResFile,°dONLNd_cnÃ*
  477. $  realNumberOfPagesInDoc  : Integer;°dONLNdÑmxÃ*
  478. $  PrintError              : LongInt;°dONLNd©wÇÃ*
  479. $  oldPort                 : GrafPtr;°dONLNdŒÅåÃ*
  480. $  thePrRecHdl             : THPrint;°dONLNdÛãñ—*
  481. %  thePrPort               : TPPrPort;°dONLNdï†÷*
  482. &  theStatus               : TPrStatus;°dONLNd@©¥1*BEGIN°dONLNdF≥æw*
  483.   GetPort(oldPort);°dONLNdZ«“1*  {**°dONLNd`—‹∑*
  484. S      UnLoadTheWorld will swap out ALL unneeded code segments and data that are NOT°dONLNd¥€Ê^*
  485.       required°dONLNd√ÂÖ*
  486. I      during print time. Your print code must be a separate code segment.°dONLNd
  487. Ô˙1*
  488.   **}°dONLNd˘m*
  489.   UnLoadTheWorld;°dONLNd%
  490. *4  thePrRecHdl := THPrint(NewHandle(SIZEOF(TPrint)));°dONLNdZ!,!*5  IF (MemError = noErr) AND (thePrRecHdl <> NIL) THEN°dONLNdê+6E*
  491.         BEGIN°dONLNdö5@Y*
  492.  
  493.       PrOpen;°dONLNd®?JΩ*
  494. !        IF (PrError = noErr) THEN°dONLNd ITc*
  495.           BEGIN°dONLNd⁄S^c*
  496.             {**°dONLNdÍ]hä*
  497. J                Save the current resource file (i.e. the printer driver's)°dONLNd5grä*
  498. J                so the driver will not lose its resources upon return from°dONLNdÄq|Æ*
  499.                 the pIdleProc.°dONLNdü{Üh*
  500.              **}°dONLNd∞ÖêÔ*
  501. +            printmgrsResFile := CurResFile;°dONLNd‹èö÷*
  502. &            PrintDefault(thePrRecHdl);°dONLNd£Æ—*%            IF (PrError = noErr) THEN°dONLNd)≠∏w*
  503.               BEGIN°dONLNd=∑¬*
  504. 2                IF (PrStlDialog(thePrRecHdl)) THEN°dONLNdp¡Ãã*
  505.                   BEGIN°dONLNdàÀ÷ã*
  506.                     {**°dONLNd†’‡î*
  507. L                        DetermineNumberOfPagesinDoc determines the number of°dONLNdÌflÍ®*
  508. P                        pages contained in the document by comparing the size of°dONLNd>ÈÙº*
  509. T                        the document with rPage from the TPrInfo record (IM II-150).°dONLNdìÛ˛î*
  510. L                        It returns the number of pages required to print the°dONLNd‡˝l*
  511. D                        document for the currently selected printer.°dONLNd%ê*
  512.                      **}°dONLNd>&Ö*I                    realNumberOfPagesinDoc := DetermineNumberOfPagesinDoc°dONLNdà%0£*
  513. O                                                  (thePrRecHdl^^.prInfo.rPage);°dONLNdÿ9D&*6                    IF (PrJobDialog(thePrRecHdl)) THEN°dONLNdCNü*
  514.                       BEGIN°dONLNd,MXü*
  515.                         {**°dONLNdHWbô*
  516. M                            Get the number of copies of the document that the°dONLNdñal®*
  517. P                            user wants printed from iCopies of the TPrJob record°dONLNdÁkv‡*
  518. (                            (IM II-151).°dONLNduħ*
  519.                          **} ∂4∂˘
  520. *22) of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇƒ◊#ˇ ˇˇˇˇ#◊ 
  521. IR,Times
  522. .+Z-Developer Support Center(-Ê October 1990 /X/,
  523. Courier
  524.     °dONLNd<"ö(>ZF                        numberOfCopies := thePrRecHdl^^.prJob.iCopies;°dONLNdG+<6√*                        {**°dONLNdc5<@Ω*
  525. M                            Get the first and last pages of the document that°dONLNd±?<J÷*
  526. R                            were requested to be printed by the user from iFstPage°dONLNdI<TΩ*
  527. M                            and iLastPage from the TPrJob record (IM II-151).°dONLNdRS<^»*
  528.                          **}°dONLNdog<rÜ*B                        firstPage := thePrRecHdl^^.prJob.iFstPage;°dONLNd≤q<|Å*
  529. A                        lastPage := thePrRecHdl^^.prJob.iLstPage;°dONLNdÙÖ<ê√*                        {**°dONLNdè<öw*
  530. ?                            Print "all" pages in the print loop°dONLNdPô<§»*
  531.                          **}°dONLNdm≠<∏^*:                        thePrRecHdl^^.prJob.iFstPage := 1;°dONLNd®∑<¬m*
  532. =                        thePrRecHdl^^.prJob.iLstPage := 9999;°dONLNdÊÀ<÷√*                        {**°dONLNd’<‡Ω*
  533. M                            Determine the "real" number of pages contained in°dONLNdPfl<ÍΩ*
  534. M                            the document.  Without this test, you would print°dONLNdûÈ<Ùˇ*
  535. '                            9999 pages.°dONLNdΔÛ<˛»*
  536.                          **}°dONLNd„<ã*C                        IF (realNumberOfPagesinDoc < lastPage) THEN°dONLNd'<m*
  537. =                          lastPage := realNumberOfPagesinDoc;°dONLNde%<0‡*T                        PrintingStatusDialog := GetNewDialog(257, NIL, POINTER(-1));°dONLNd”9<D√*                        {**°dONLNdÔC<N€*
  538. S                            Print the number of copies of document requested by the°dONLNdFM®X⁄+l
  539.  
  540.       user°dONLNdQW<bJ(~Z6                            from the Print Job Dialog.°dONLNdàa<l»*
  541.                          **}°dONLNd•u<Äh*<                        For copies := 1 To numberOfCopies Do°dONLNd‚<ä◊*
  542.                           BEGIN°dONLNdì<û◊*                            {**°dONLNd"ù<®Ã*
  543. P                                Install a pointer to your pIdle proc in my print°dONLNdsß<≤_*
  544. record.°dONLNd{±<º‹*
  545.                               **}°dONLNdúª<Δm*
  546. =                             thePrRecHdl^^.prJob.pIdleProc :=°dONLNd⁄≈<–æ*
  547. @checkMyPrintDialogButton;°dONLNdıŸ<‰◊*                            {**°dONLNd„<Ó÷*
  548. R                                Restore the resource file to the printer driver's.°dONLNdhÌ<¯‹*
  549.                               **}°dONLNdâ˜<Y*
  550. 9                            UseResFile(printmgrsResFile);°dONLNd√ <Æ*J                            thePrPort := PrOpenDoc(thePrRecHdl, NIL, NIL);°dONLNd<*E*5                            IF (PrError = noErr) THEN°dONLNdD)<4Î*
  551. #                              BEGIN°dONLNdh3<>Î*
  552. #                                {**°dONLNdå=<H∏*
  553. L                                    Print the range of pages of the document°dONLNdŸG<Ri*
  554.     requested°dONLNd„Q<\Æ*
  555. J                                    by the user from the Print Job Dialog.°dONLNd    .[<f*
  556. $                                 **}°dONLNd    Se<pT*
  557. 8                                pageNumber := firstPage;°dONLNd    åo<z¬*
  558. N                                WHILE ((pageNumber <= lastPage) AND (PrError =°dONLNd    €y<Ñn*
  559.  
  560. noErr)) DO ∂X∂
  561. *.#PR 10 - A Printing Loop That Cares…(Œˇ3) of 12(‰ZM.PR.PrintLoopˇ◊#ˇ ˇˇˇˇ#◊ 
  562. IR,Times
  563. .+6-Macintosh Technical Notes /4/˘,
  564. Courier
  565.     °dONLNd(€*'                                  BEGIN°dONLNd41®<–+ê    { **"P3    °dONLNdB;ÃFÖ+$
  566. %If we've crossed a 128-page boundary,"Z3    °dONLNdmEÃPÖ*
  567. %close the current print file, send it"d3    °dONLNdòOÃZè*
  568. 'to the printer if necessary, and open a"n3    °dONLNd≈YÃd
  569. *
  570.  
  571. new document."x3    °dONLNd◊c®n–(äΔ    ** }"Ç3    "å3    °dONLNdÏw®Ç∂*6    IF (pageNumber - firstPage) MOD iPFMaxPgs = 0 THEN"ñ3    °dONLNd#ÅåÔ(®6+                                      BEGIN"†3    °dONLNdOãñ{*
  572. G                                        IF pageNumber <> firstPage THEN"™3    °dONLNdóï†*
  573. /                                          BEGIN"¥3    °dONLNd«ü™b*
  574. B                                            PrCloseDoc(thePrPort);"æ3    °dONLNd
  575. ©¥£*
  576. O                                            IF (thePrRecHdl^^.prJob.bJDocLoop ="»3    °dONLNdZ≥æO*
  577. bSpoolLoop)"“3    °dONLNdfΩ»Ä*
  578. H                                              AND (PrError = noErr) THEN"‹3    °dONLNdØ«“≤*
  579. R                                              PrPicFile(thePrRecHdl, NIL,NIL, NIL,"Ê3    °dONLNd—‹O*
  580. theStatus);"3    °dONLNd€Êº*
  581. T                                            thePrPort := PrOpenDoc(thePrRecHdl, NIL,"˙3    °dONLNdcÂ1*
  582. NIL);"3    °dONLNdiÔ˙˛*
  583. .                                          END;"3    °dONLNdò˘Ù*
  584. ,                                        END;"3    °dONLNd…
  585. ®M+ê!      PrOpenPage(thePrPort, NIL);°dONLNdÎ!,S(H6?                                      IF (PrError = noErr) THEN°dONLNd++6˘*
  586. -                                        BEGIN°dONLNdY5@˘*
  587. -                                          {**°dONLNdá?J®*
  588. P                                              rPage (IM II-150) is the printable°dONLNdÿITô*
  589. M                                              area for the currently selected°dONLNd&S^@*
  590. printer.°dONLNd/]h≠*
  591. Q                                              By passing the current enables your°dONLNdÅgrJ*
  592.  
  593. app to use°dONLNdëqÃ|º+¥
  594. 0      the same routine to draw to the screen and°dONLNd¬{Ü'(¢6the°dONLNdÀÖÃêI+¥
  595.       printer's GrafPort.°dONLNdÂèö˛(∂6.                                           **}°dONLNd£Æ®*P                                          DrawStuff (thePrRecHdl^^.prInfo.rPage,°dONLNdf≠∏Ö*
  596. I                                                     GrafPtr (thePrPort),°dONLNd±∑¬]*
  597. A                                                     pageNumber);°dONLNdÛ¡ÃÙ*
  598. ,                                        END;°dONLNd À÷I*
  599. =                                      PrClosePage(thePrPort);°dONLNd^’‡g*
  600. C                                      pageNumber := pageNumber + 1;°dONLNd¢flÍq*
  601. E                                  END;  {**  End pagenumber loop  **}°dONLNdËÈÙ¬*
  602. "                              END;°dONLNd Û˛*
  603. 2                            PrCloseDoc(thePrPort);°dONLNd>˝5*
  604. 9                          END;  {**  End copies loop  **}°dONLNdx©*                          {**°dONLNdñ&≤*
  605. R                              The printing job is being canceled by the request of°dONLNdÈ%0∑*
  606. S                              the user from the Print Style Dialog or the Print Job°dONLNd    =/:≤*
  607. R                              Dialog.  PrError will be set to iPrAbort to tell the°dONLNd    ê9Dû*
  608. N                              Print Manager to abort the current printing job.°dONLNd    flCNÆ*
  609.                            **}°dONLNd    ˛MXï*
  610.                       END°dONLNd
  611. Wb§*
  612.                         ELSE°dONLNd
  613. 5al≤*
  614. R                      PrSetError(iPrAbort);   {**  Cancel from the job dialog  **}°dONLNd
  615. àkvÅ*
  616.                   END°dONLNd
  617. ûuÄê*
  618.                     ELSE°dONLNd
  619. ∑ä®*
  620. P                  PrSetError(iPrAbort);   {**  Cancel from the style dialog  **} ∂4∂˘
  621. *(4) of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ
  622. x◊#ˇ ˇˇˇˇ#◊ 
  623. IR,Times
  624. .+Z-Developer Support Center(-Ê October 1990 /X/,
  625. Courier
  626.     °dONLNd<"ñ(>Z              END;°dONLNd!<,Ç*
  627.           END;°dONLNd"+<6¬*
  628. N    IF (thePrRecHdl^^.prJob.bJDocLoop = bSpoolLoop) and (PrError = noErr) THEN°dONLNdq5<@O*
  629. 7      PrPicFile(thePrRecHdl, NIL, NIL, NIL, theStatus);°dONLNd©I<T_*    {**"hW    °dONLNd±S<^«*
  630. O        Grab the printing error -- once you close the Printing Manager, PrError"rW    °dONLNd]<hÇ*
  631. doesn't return"|W    °dONLNdg<r◊*
  632.         a valid result anymore."ÜW    °dONLNd0q<|d*
  633.      **}"êW    °dONLNd9Ö<êæ*    PrintError := PrError;°dONLNdTô<§x*     PrClose;°dONLNda∑<¬_*    {**°dONLNdi¡<Ã≥*
  634. K        You do not want to report any printing errors until you have fallen°dONLNdµÀ<÷∏*
  635. L        through the printing loop. This will make sure that ALL of the Print°dONLNd’<‡Æ*
  636. J        Manager's open calls have their corresponding close calls, thereby°dONLNdMfl<Í≥*
  637. K        enabling the Print Manager to close properly and that all temporary°dONLNdôÈ<Ù*
  638. (        memory allocations are released.°dONLNd¬Û<˛d*
  639.      **}°dONLNdÀ<·*!    IF (PrintError <> noErr) THEN°dONLNdÌ<˙*
  640. &      PostPrintingErrors (PrintError);°dONLNd%<0d*    END;°dONLNd9<D“*  IF (thePrRecHdl <> NIL) THEN°dONLNd=C<Nˇ*
  641. '    DisposHandle(Handle (thePrRecHdl));°dONLNdeW<bˇ*'  IF (PrintingStatusDialog <> NIL) THEN°dONLNdéa<lˇ*
  642. '    DisposDialog(PrintingStatusDialog);°dONLNd∂u<Äõ*  SetPort(oldPort);°dONLNd <äæ*
  643. END;  {**  PrintStuff  **}
  644. °dONLNdÂï<°h*MPW C
  645.     °dONLNdÎ≠<∏€*S/*------ PrintStuff ---------------------------------------------------------------°dONLNd>≠€∏‡(‘˘-°dONLNd?∑<¬F(fiZ*/°dONLNdB¡<ÃK*
  646.  **°dONLNdFÀ<÷Ω*
  647. M **    PrintStuff will call all of the necessary Print Manager calls to print°dONLNdî’<‡—*
  648. Q **    a document. It checks PrError() after each Print Manager call. If an error°dONLNdÊfl<Í—*
  649. Q **    is found, all of the Print Manager open calls (i.e., PrOpen, PrOpenDoc...)°dONLNd8È<Ù€*
  650. S **    will have a corresponding close call before the error is posted to the user.°dONLNdåÛ<˛€*
  651. S **    You want to use this approach to make sure the Print Manager closes properly°dONLNd‡˝<*
  652. , **    and all temporary memory is released.°dONLNd
  653. <P*
  654.  **/°dONLNd<&ñ*void PrintStuff ()°dONLNd%%<0A*
  655. {°dONLNd'/<:Ø*
  656.   GrafPtr      oldPort;°dONLNd?9<D™*
  657.   short        copies,°dONLNdVC<Nπ*
  658.                firstPage,°dONLNdpM<X¥*
  659.                lastPage,°dONLNdâW<b“*
  660.                numberOfCopies,°dONLNd®a<l‹*
  661.                 printmgrsResFile,°dONLNd…k<v˙*
  662. &               realNumberOfPagesinDoc,°dONLNdu<Äæ*
  663.                pageNumber,°dONLNd <äæ*
  664.                PrintError; ∂X∂
  665. *(#PR 10 - A Printing Loop That Cares…(Œˇ5) of 12(‰ZM.PR.PrintLoopˇä◊#ˇ ˇˇˇˇ#◊ 
  666. IR,Times
  667. .+6-Macintosh Technical Notes /4/˘,
  668. Courier
  669.     °dONLNd(ü*  THPrint      thePrRecHdl;°dONLNd'2ï*
  670.   TPPrPort     thePrPort;°dONLNd61<ï*
  671.   TPrStatus    theStatus;°dONLNdPEP|*  GetPort(&oldPort);°dONLNdeYd,* /**°dONLNdjcnä*
  672. J     UnLoadTheWorld will swap out ALL unneeded code segments and data that°dONLNdµmxè*
  673. K     are NOT required during print time. Your print code must be a separate°dONLNdwÇr*
  674.      code segment.°dONLNdÅå1*
  675.   **/°dONLNdï†|*  UnLoadTheWorld ();°dONLNd/ü™+*
  676. 7  thePrRecHdl = (THPrint)  NewHandle (sizeof (TPrint));°dONLNdg≥æ,* /**°dONLNdlΩ»Ä*
  677. H     Check to make sure that the memory manager did not produce an error°dONLNdµ«“î*
  678. L     when it allocated the print record handle and make sure it did not pass°dONLNd—‹ã*
  679.      back a nil handle.°dONLNd€Ê1*
  680.   **/°dONLNd Ô˙*0  if (MemError() == noErr && thePrRecHdl != nil)°dONLNdQ˘1*
  681.     {°dONLNdWc*
  682.       PrOpen();°dONLNdg"©*      if (PrError() == noErr)°dONLNdÖ!,E*
  683.             {°dONLNdè+6T*
  684.          /**°dONLNdú5@è*
  685. K              Save the current resource file (i.e. the printer driver's) so°dONLNdË?Jº*
  686. T              the driver will not lose its resources upon return from the pIdleProc.°dONLNd=ITY*
  687.  
  688.           **/°dONLNdKS^Í*
  689. *          printmgrsResFile = CurResFile();°dONLNdv]hÃ*
  690. $          PrintDefault(thePrRecHdl);°dONLNdõq|Ω*!          if (PrError() == noErr)°dONLNdΩ{ÜY*
  691.  
  692.             {°dONLNdÀÖêÔ*
  693. +              if (PrStlDialog(thePrRecHdl))°dONLNd˜èöm*
  694.                 {°dONLNd    ô§|*
  695.                  /**°dONLNd£Æ£*
  696. O                     DetermineNumberOfPagesinDoc determines the number of pages°dONLNdn≠∏º*
  697. T                     contained in the document by comparing the size of the document°dONLNd√∑¬∑*
  698. S                     with rPage from the TPrInfo record (IM II-150). It returns the°dONLNd¡Ãî*
  699. L                     number of pages required to print the document for the °dONLNdfÀ`÷(+H
  700. (             currently selected printer.°dONLNdè’‡Å(¸6                  **/°dONLNd•ÈÙv*F                  realNumberOfPagesinDoc = DetermineNumberOfPagesinDoc°dONLNdÏÛ˛î*
  701. L                                             ((**thePrRecHdl).prInfo.rPage);°dONLNd9*/                  if (PrJobDialog(thePrRecHdl))°dONLNdjÅ*
  702.                     {°dONLNdÄ&ê*
  703.                      /**°dONLNdô%0®*
  704. P                          Get the number of copies of the document that the user°dONLNdÎ/:®*
  705. P                          wants printed from iCopies of the TPrJob record (IM II°dONLNd;/®:≠(VΔ-°dONLNd<9D1(`6151).°dONLNdBCNï*
  706.                       **/°dONLNd\Wbq*E                      numberOfCopies = (**thePrRecHdl).prJob.iCopies;°dONLNd¢kvö*                       /**°dONLNdΩuÄî*
  707. L                           Get the first and last pages of the document that°dONLNd
  708. ä≠*
  709. Q                           were requested to be printed by the user from iFstPage ∂4∂˘
  710. *(6) of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇJ◊#ˇ ˇˇˇˇ#◊ 
  711. IR,Times
  712. .+Z-Developer Support Center(-Ê October 1990 /X/,
  713. Courier
  714.     °dONLNd<"∏(>ZL                           and iLastPage from the TPrJob record (IM II-151).°dONLNdM!<,√*
  715.                         **/°dONLNdi5<@Å*A                      firstPage = (**thePrRecHdl).prJob.iFstPage;°dONLNd´?<J|*
  716. @                      lastPage = (**thePrRecHdl).prJob.iLstPage;°dONLNdÏS<^æ*                       /**°dONLNd]<hr*
  717. >                           Print "all" pages in the print loop°dONLNdFg<r√*
  718.                         **/°dONLNdb{<ÜY*9                      (**thePrRecHdl).prJob.iFstPage = 1;°dONLNdúÖ<êh*
  719. <                      (**thePrRecHdl).prJob.iLstPage = 9999;°dONLNdŸô<§æ*                       /**°dONLNdÙ£<Æ—*
  720. Q                           Determine the "real" number of pages contained in the °dONLNdH≠®∏‘+l
  721. <           document. Without this test, you would print 9999°dONLNdÖ∑<¬Z(fiZpages.°dONLNdå¡<Ã√*
  722.                         **/°dONLNd®’<‡h*<                      if (realNumberOfPagesinDoc < lastPage)°dONLNdÊfl<Í^*
  723. :                        lastPage = realNumberOfPagesinDoc;°dONLNd!Û<˛‡*T                      PrintingStatusDialog = GetNewDialog(257, nil, (WindowPtr) -1);°dONLNdv<æ*                       /**°dONLNdë<ï*
  724. E                           Print the number of copies of the document°dONLNd◊<&≥*
  725. K                           requested by the user from the Print Job Dialog.°dONLNd#%<0√*
  726.                         **/°dONLNd?/<:Æ*
  727. J                      for (copies = 1; copies <= numberOfCopies; copies++)°dONLNdä9<Dπ*
  728.                         {°dONLNd§C<N»*
  729.                          /**°dONLNd¡M<XΩ*
  730. M                             Install a pointer to your pIdle proc in my print°dONLNdW<b_*
  731. record.°dONLNda<lÕ*
  732.                           **/°dONLNd5k<vc*
  733. ;                          (**thePrRecHdl).prJob.pIdleProc =°dONLNdqu<Äπ*
  734. checkMyPrintDialogButton;°dONLNdãâ<î»*                         /**°dONLNd®ì<û«*
  735. O                             Restore the resource file to the printer driver's.°dONLNd¯ù<®Õ*
  736.                           **/°dONLNd±<ºO*7                          UseResFile(printmgrsResFile);°dONLNdNª<Δü*
  737. G                          thePrPort = PrOpenDoc(thePrRecHdl, nil, nil);°dONLNdñœ<⁄1*1                          if (PrError() == noErr)°dONLNd»Ÿ<‰Õ*
  738.                             {°dONLNdÊÌ<¯‹*                              /**°dONLNd˜<©*
  739. I                                 Print the range of pages of the document°dONLNdR< —*
  740. Q                                 requested by the user from the Print Job Dialog.°dONLNd§ <·*
  741. !                              **/°dONLNdΔ< E*
  742. 5                              pageNumber = firstPage;°dONLNd¸<*÷*
  743. R                              while (pageNumber <= lastPage && PrError() == noErr)°dONLNdO)<4·*
  744. !                                {°dONLNdò=ÃHÙ+ê     /**"\W    °dONLNd¶GR∏+$
  745. (   If we've crossed a 128-page boundary,"fW    °dONLNd‘Q\∏*
  746. (   close the current print file, send it"pW    °dONLNd    [f¬*
  747. *   to the printer if necessary, and open a"zW    °dONLNd    2ep@*
  748.    new document."ÑW    °dONLNd    GoÃzÙ(ñÍ     **/"éW    "òW     ∂X∂
  749. (ŒZ#PR 10 - A Printing Loop That Cares…(Œˇ7) of 12(‰ZM.PR.PrintLoopˇD◊#ˇ ˇˇˇˇ#◊ 
  750. IR,Times
  751. .+6-Macintosh Technical Notes /4/˘,
  752. Courier
  753.     °dONLNd®(ß+ê3     if ((pageNumber - firstPage) % iPFMaxPgs == 0)"<3    °dONLNd8'®2–*
  754.        {"F3    °dONLNdE1®<a*
  755. %         if (pageNumber != firstPage)"P3    °dONLNdo;®F‰*
  756.            {"Z3    °dONLNdÄE®PW*
  757. #             PrCloseDoc(thePrPort);"d3    °dONLNd®O®Z¨*
  758. 4             if (((**thePrRecHdl).prJob.bJDocLoop =="n3    °dONLNd›Yd≠(Ä6Q                                             bSpoolLoop) && (PrError() == noErr))"x3    °dONLNd/cn≤*
  759. R                                             PrPicFile(thePrRecHdl, nil, nil, nil,"Ç3    °dONLNdÇmxg*
  760. C                                                       &theStatus);"å3    °dONLNd w®Ç¨+ê
  761. 4             thePrPort = PrOpenDoc(thePrRecHdl, nil,"ñ3    °dONLNdˇÅåq(®6E                                                                nil);"†3    °dONLNdEãñÍ*
  762. *                                         }"™3    °dONLNdpï†÷*
  763. &                                     }"¥3    °dONLNdú©®¥H+ê      PrOpenPage(thePrPort, nil);°dONLNdΩΩ»5(‰69                                  if (PrError() == noErr)°dONLNd¯«“—*
  764. %                                    {°dONLNd—‹‡*
  765. (                                     /**°dONLNdG€Ê®*
  766. P                                         rPage (IM II-150) is the printable area°dONLNdòÂ®*
  767. P                                         for the currently selected printer. By °dONLNdÌÔÃ˙û+¥
  768. *     passing the current port to the draw °dONLNd˘Ã∑*
  769. /     routine, enables your app to use the same °dONLNdQã*
  770. +     routine to draw to the screen and the °dONLNdÅ
  771. ÃD*
  772.      printer's GrafPort.°dONLNdö"Â(>6)                                      **/°dONLNdƒ!,û*
  773. N                                      DrawStuff ((**thePrRecHdl).prInfo.rPage,°dONLNd+6≤*
  774. R                                                 (GrafPtr) thePrPort, pageNumber);°dONLNdg5@—*
  775. %                                    }°dONLNdçIT5*9                                  PrClosePage(thePrPort);°dONLNd«S^*
  776. /                                  pageNumber++;°dONLNd˜]hX*
  777. @                                }  /**  End pageNumber loop  **/°dONLNd8gr©*
  778.                             }°dONLNdVq|*
  779. 0                          PrCloseDoc(thePrPort);°dONLNdá{Ü*
  780. 3                        } /**  End copies loop  **/°dONLNdªÖêÅ*
  781.                     }°dONLNd—èöÜ*
  782.                    /**°dONLNdËô§£*
  783. O                       The printing job is being canceled by the request of the°dONLNd8£Æ®*
  784. P                       user from the Print Style Dialog or the Print Job Dialog.°dONLNdâ≠∏≤*
  785. R                       PrError will be set to PrAbort to tell the Print Manager to°dONLNd‹∑¬&*
  786. 6                       abort the current printing job.°dONLNd¡Ãã*
  787.                     **/°dONLNd+À÷Ü*
  788.                   else°dONLNdB’‡≠*
  789. Q                    PrSetError (iPrAbort);   /**  cancel from the job dialog  **/°dONLNdîflÍm*
  790.                 }°dONLNd¶ÈÙr*
  791.               else°dONLNdπÛ˛£*
  792. O                PrSetError (iPrAbort);   /**  cancel from the style dialog  **/°dONLNd    
  793. ˝Y*
  794.  
  795.             }°dONLNd    E*
  796.             }°dONLNd    "&≤*R      if (((**thePrRecHdl).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr))°dONLNd    u%0:*
  797. :        PrPicFile(thePrRecHdl, nil, nil, nil, &theStatus);°dONLNd    ∞9DJ*
  798.        /**"X3    °dONLNd    ªCN≤*
  799. R           Grab the printing error -- once you close the Printing Manager, PrError"b3    °dONLNd
  800. MX;*
  801. doesn't"l3    °dONLNd
  802. W<b‹+$
  803.     returna valid result anymore."v3    °dONLNd
  804. 9alJ(à6
  805.        **/"Ä3    °dONLNd
  806. DuÄ©*      PrintError = PrError(); ∂4∂˘
  807. *28) of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ\◊#ˇ ˇˇˇˇ#◊ 
  808. IR,Times
  809. .+Z-Developer Support Center(-Ê October 1990 /X/,
  810. Courier
  811.     °dONLNd<"å(>Z      PrClose();°dONLNd+<6n*
  812.        /**°dONLNd5<@¬*
  813. N           You do not want to report any printing errors until you have fallen°dONLNdk?<J«*
  814. O           through the printing loop. This will make sure that ALL of the Print°dONLNdªI<TΩ*
  815. M           Manager's open calls have their corresponding close calls, thereby°dONLNd    S<^¬*
  816. N           enabling the Print Manager to close properly and that all temporary°dONLNdX]<h*
  817. +           memory allocations are released.°dONLNdÑg<rs*
  818.         **/°dONLNdêq<|“*
  819.       if (PrintError != noErr)°dONLNd∞{<Ü*
  820. (        PostPrintingErrors (PrintError);°dONLNdŸÖ<êU*
  821.     }°dONLNdflô<§π*  if (thePrRecHdl != nil)°dONLNd˘£<Æˇ*
  822. '    DisposHandle((Handle) thePrRecHdl);°dONLNd!∑<¬Ê*"  if (PrintingStatusDialog != nil)°dONLNdD¡<Ãˇ*
  823. '    DisposDialog(PrintingStatusDialog);°dONLNdl’<‡õ*  SetPort(oldPort);°dONLNdÄfl<Í•*
  824. }  /** PrintStuff **/ ∂X∂
  825. (ŒZ#PR 10 - A Printing Loop That Cares…(Œˇ9) of 12(‰ZM.PR.PrintLoopˇ¨◊#ˇ ˇˇˇˇ#◊ 
  826. IR,Times
  827. .+6-Macintosh Technical Notes /4/˘
  828. °dONLNd)8#*'%Checking And Handling Printing Errors
  829. °dONLNd&EQ•*RAn application should always check for error conditions while printing by calling ,
  830. Courier°dONLNdxD•P÷(m√PrError°dONLNdE÷Q⁄)1.°dONLNdÇQ]I(z6PrError°dONLNdâRI^©)1 returns errors from °dONLNdûR©^⁄)`<the Printing Manager (and some AppleTalk and OS errors) that°dONLNd€^jÄ(Ü6occur during printing.°dONLNdÚwÉΔ*"As the example code demonstrates, °dONLNdwΔÉH)Æan application should call °dONLNd/vHÇy)ÇPrError°dONLNd6wyÉ⁄)1 after each call to a°dONLNdLÑê_(¨6BPrinting Manager function or procedure.  By consistently checking °dONLNdéÉ_èê(¨}PrError°dONLNdïÑêêΔ)1  after each °dONLNd°ÑΔê⁄)6call,°dONLNdßêú’(∏6`the application is able to catch any errors created at print time and report them to a user via °dONLNdê’ú⁄(∏Ûa°dONLNd    ú®‡(ƒ6*dialog box in a clean and graceful manner.°dONLNd4¥¿f*FThe following section outlines some general error-handling guidelines.°dONLNd{Õ*Ÿ.+•°dONLNd}Õ7Ÿ∏)
  831. You should avoid calling °dONLNdñÃ∏ÿÈ)ÅPrError°dONLNdùÕÈŸ)1 within °dONLNd•ÕŸ∂)(!your pIdle procedure; errors that°dONLNd«Ÿ7ÂÎ(U(occur while it is executing are usually °dONLNdÔŸÎÂ∂)¥*temporary and serve only as internal flags°dONLNdÂ7Òˆ(
  832. U%for communication within the printer °dONLNd?ˆÒ∂)ø$driver—they are not intended for the°dONLNddÚ7˛˚(U*application.  If you absolutely must call °dONLNdéÒ˚˝,)ƒPrError°dONLNdïÚ,˛R)1 within °dONLNdùÚR˛∂)&your idle procedure,°dONLNd≤˛7
  833. õ(&ULand an error occurs, never abort printing within the idle procedure itself. °dONLNd˛˛õ
  834. ∂(&π Wait°dONLNd
  835. 7ë(2Uuntil the last called °dONLNd
  836. ë∂)Z@printing procedure returns, then check to see if the error still°dONLNd[7"ƒ(>Uremains.  Attempting to abort °dONLNdyƒ"∂)ç3printing within an idle procedure is a guarantee of°dONLNd≠"7.v(JUcertain death.°dONLNdº:*F.(bH•°dONLNdæ:7Fê)
  837. Upon detecting an °dONLNd–:êF∂)Y>error after the completion of a printing routine, stop drawing°dONLNdF7Rç(nUat that point, and °dONLNd"FçR∂)V:proceed to the next procedure to close any previously made°dONLNd]S7_m({U open calls. °dONLNdiSm_[)63 For example, if you detect an error after calling °dONLNdúR[^ö)Ó    PrOpenDoc°dONLNd•Sö_∂)?, skip°dONLNd¨`7lC(àUto °dONLNdØ`Clm)     the next °dONLNd∏_mk≥)*
  838. PrCloseDoc°dONLNd¬`≥ll)F).  Or, if you get an error after calling °dONLNdÎ_lk≤)π
  839. PrOpenPage°dONLNdı`≤l∂)F,°dONLNd˜m7yÇ(ïUskip to the next °dONLNdlÇxœ)K PrClosePage°dONLNdmœyÊ)M and °dONLNdlÊx,)
  840. PrCloseDoc°dONLNd"m,yä)F.  Remember that if °dONLNd6mäy∂)^you have°dONLNd?z7ÜV(¢Ucalled °dONLNdFyVÖÄ)PrOpen°dONLNdLzÄÜ?)*', then you must call the corresponding °dONLNdsy?Öp)øPrClose°dONLNdzzpÜÅ)1 to °dONLNd~zÅÜ∂) ensure that°dONLNdäÜ7í0(ÆU2printing closes properly and all temporary memory °dONLNdºÜ0í∂)˘allocations are released and°dONLNdŸí7ûò(∫Ureturned to the heap.°dONLNdÔ™*∂.(“H•°dONLNdÒ™7∂:)
  841. 6Do not display any alert or dialog boxes to report an °dONLNd'™:∂∂(“Xerror until the end of the°dONLNdB∂7¬©(fiUprinting loop.  Once at °dONLNdZ∂©¬∂)r8the end, check for the error again; if there is no error°dONLNdì¬7Œ`(ÍU@assume that printing completed normally.  If the error is still °dONLNd”¬`Œ∂(Í~present, then you°dONLNdÂŒ7⁄ä(ˆUcan alert the user.°dONLNd˙Ê7Úó*MThis technique is important for two reasons.  First, if you display a dialog °dONLNdGÊóÚ∂(µbox in°dONLNdNÚ7˛´(UJthe middle of the printing loop, it could cause errors that can terminate °dONLNdòÚ´˛∂(…an°dONLNdõ˛7
  842. -(&U3otherwise normal job.  For example, if the printer °dONLNdŒ˛-
  843. ∂)ˆis an AppleTalk printer, the°dONLNdÎ
  844. 7à(2UBconnection can be terminated abnormally since the driver would be °dONLNd    -
  845. à∂(2¶    unable to°dONLNd    77"a(>Urespond °dONLNd    ?a"∂)*Dto AppleTalk requests received from the printer while the dialog box°dONLNd    Ñ"7.Û(JU%was waiting for input from the user. °dONLNd    ©"Û.∂)º& If the printer does not hear from the°dONLNd    –.7:    (VU-Macintosh with a short period of time (e.g., °dONLNd    ˝.    :∂)“#30 seconds), it times out, assuming°dONLNd
  846. !:7F=(bU5that the Macintosh is no longer there, which results °dONLNd
  847. V:=F∂(b[in a prematurely broken°dONLNd
  848. nF7Rã(nUGconnection causing another error to which the application must respond. ∂4∂˘
  849. (Œ610)
  850.  of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇé◊#ˇ ˇˇˇˇ#◊ 
  851. IR,Times
  852. .+Z-Developer Support Center(-Ê October 1990 /X/
  853. °dONLNd[#—(?yIn addition, the driver °dONLNd—#⁄)v0may have already displayed its own dialog box in°dONLNdI#[/Ã(KyJresponse to an error.  In this instance, the driver posts an error to let °dONLNdì#Ã/⁄(KÍthe°dONLNdó/[;…(WyJapplication know that something went wrong and it should abort printing.  °dONLNd·/…;⁄(WÁFor°dONLNdÂ;[G∑(cyexample, when the °dONLNd˜;∑G⁄)\<LaserWriter driver detects that the Laser Prep version which°dONLNd4G[SΔ(oyMhas been downloaded to the LaserWriter is different than that with which the °dONLNdÅGΔS⁄(o‰user°dONLNdÜS[_*({y0is trying to print, it displays the appropriate °dONLNd∂S*_⁄)œ$dialog box informing the user of the°dONLNd€_[k¡(áysituation and giving °dONLNd_¡k⁄)f:him the option of reinitializing the printer.  If the user°dONLNd+k[wá(ìyAchooses to cancel printing, the driver posts an error to let the °dONLNdlkáw⁄(ì•application know°dONLNd}w[Éx(üythat it °dONLNdÖwxÉ⁄)Kneeds to abort, but since the driver has already taken care of the error by°dONLNd—É[èå(´y?displaying a dialog box, the error is reset to zero before the °dONLNdÉåè⁄(´™printing loop is°dONLNd!è[õÃ(∑yJcomplete.  The application should check for the error again at the end of °dONLNdkèÃõ⁄(∑Íthe°dONLNdoõ[ßC(√y7printing loop, and if it still indicates an error, the °dONLNd¶õCß⁄)Ë application can then display the°dONLNd«ß[≥…(œyappropriate dialog box.°dONLNdfl¿NÃR(Ël•°dONLNd·¿[Ãë)
  854.     If using ,
  855. Courier°dONLNdÍøëÀ–)6    PrGeneral°dONLNdÛ¿–Ã⁄)?., be prepared to receive the following errors:°dONLNd#Ã[ÿö(ıy    NoSuchRsl°dONLNd,ÕöŸ•)?, °dONLNd.Õÿ‰)     OpNotImpl°dONLNd7Õ‰Ÿ)?, and °dONLNd=ÃÿT)# resNotFound°dONLNdHÕTŸß)M.  In all three °dONLNdXÕߟ⁄)S
  856. cases, the°dONLNdcŸ[¬(yapplication should be °dONLNdyŸ¬Â⁄)g;prepared to continue to print without using the features of°dONLNdµÂ[Òƒ(
  857. ythat particular opcode.°dONLNdŒ˛[
  858. Ê*However, in the case of the °dONLNdÍ˝Ê    3)ã resNotFound°dONLNdı˛3
  859. Ç)M error, it means °dONLNd˛Ç
  860. ⁄)Othe current printer°dONLNd [‘(3ydriver does not support °dONLNd2
  861. ‘)y    PrGeneral°dONLNd; ƒ)?#.  This lack of support should not °dONLNd^ ƒ⁄)±be a°dONLNdc[#](?y8problem for an application, but it needs to be prepared °dONLNdõ]#⁄(?{to deal with this error.  If°dONLNd∏$[0ú(Lyyou receive a °dONLNdΔ#ú/È)A resNotFound°dONLNd—$È0 )M  error from °dONLNd›# /Q)7PrError°dONLNd‰$Q0¥)1, clear the error with °dONLNd˚$¥0⁄)c    a call to°dONLNd0[<∂(Yy
  862. PrSetError(0)°dONLNd1∂=Û)[
  863. ; otherwise, °dONLNd0Û<$)=PrError°dONLNd&1$=ó)1 might still contain this °dONLNd@1ó=⁄)serror the next°dONLNdO=[I´(eyFtime you check it, which would prevent your application from printing.
  864. °dONLNdñg<vU(íZ)Canceling or Pausing the Printing Process
  865. °dONLNd¿Ç<éµ*If you install a procedure °dONLNd€ǵé˛)yEfor handling requests to cancel printing, with an option to pause the°dONLNd!é<ö@(∂Z-printing process, beware of timeout problems °dONLNdNé@ö˛(∂^!when printing to the LaserWriter.°dONLNdqö<¶{(¬Z=Communication between the Macintosh and the LaserWriter must °dONLNdÆö{¶˛(¬ôbe maintained to prevent a°dONLNd…¶<≤(ŒZ^job or a wait timeout.  If there is no communication for a period of time (over two minutes), °dONLNd'¶≤˛(Œthe°dONLNd+≤<æ≈(⁄ZYprinter times out and the print job terminates due to a wait  timeout.  Or, if the print °dONLNdÑ≤≈æ˛(⁄„ job requires°dONLNdëæ< Ÿ(ÊZ"more than three minutes to print, °dONLNd≥柠˛)ù?the print job terminates due to a job timeout.  Since, there is°dONLNdÛ <÷(ÚZ,no good method to determine to what type of °dONLNd     ÷˛)◊4printer an application is printing, it is probably a°dONLNd    T÷<‚∞(˛ZMgood idea to document the possibility of a LaserWriter timing out for a user °dONLNd    °÷∞‚˛(˛Œwho chooses to°dONLNd    ∞‚<ÓË(
  866. Z$select “pause” for over two minutes.
  867. °dONLNd    ’ <K*-%Error Messages Created In Print Land…
  868. °dONLNd    ˚'<3%*0The Printing Manager reports the error messages °dONLNd
  869. +'%3˛)È/covered in this section.  If an error that does°dONLNd
  870. [3<?s([Z not belong °dONLNd
  871. f3s?˛)7Mto the Printing Manager occurs, the Printing Manager puts it into low memory,°dONLNd
  872. ¥@<L (hZ)where it can be retrieved with a call to °dONLNd
  873. ›? K=)–PrError°dONLNd
  874. ‰@=LG)1, °dONLNd
  875. Ê@GL˛)
  876. $and terminates the printing loop, if°dONLNd L<XG(tZ7necessary.  As already documented, if you encounter an °dONLNd BLGX˛(te'error in the middle of a printing loop,°dONLNd jX<d“(ÄZWdo not jump out; fall through the loop and let the Printing Manager terminate properly. ∂X∂
  877. *N#PR 10 - A Printing Loop That Cares…(Œ˙11)
  878.  of 12(‰ZM.PR.PrintLoopˇN◊#ˇ ˇˇˇˇ#◊ 
  879. IR,Times
  880. .+6-Macintosh Technical Notes /4/˘
  881. °dONLNd<){+$
  882. Error Code°dONLNd Ñ)∂)HConstant°dONLNd)1)l Description HXHñ°dONLNd!+Z7`(Sx0,
  883. Courier°dONLNd#*Ñ6ß)*noErr°dONLNd)+7)lNo error°dONLNd38ND`(`l128°dONLNd77ÑCº)6iPrAbort°dONLNd@8Dk)lAbort the printing process°dONLNd_DPK* (Command-period)°dONLNdqQV]`(yt-1°dONLNdtPÑ\—). iPrSavePFil°dONLNdÄQ]e)lProblem saving print file°dONLNdõ^Pj`(Ün-17°dONLNdü]Ñi )4
  884. controlErr°dONLNd™^ju)lUnimplemented Control call°dONLNdΔkPw`(ìn-27°dONLNd jÑvº)4iIOAbort°dONLNd”kw.)l I/O problems°dONLNd·xJÑ`(†h-108°dONLNdÊwÑÉ—): iMemFullErr°dONLNdÚxÑ^)lNot enough heap space £X£ñ°dONLNdù©.(≈6<The following errors are specific to the LaserWriter family:°dONLNdF∂D¬`+,-4101°dONLNdM∂¬o)¨Printer not found or closed ‘X‘˘°dONLNdj¬DŒ`(Íb-4100°dONLNdq¬Œ[)¨Connection just closed°dONLNdâŒD⁄`(ˆb-4099°dONLNdêŒ⁄S)¨Write request too big°dONLNdß⁄DÊ`(b-4098°dONLNdÆ⁄ÊY)¨Request already active°dONLNdΔÊDÚ`(b-4097°dONLNdÕÊÚ^)¨Bad connection refnum°dONLNd‰ÚD˛`(b-4096°dONLNdÎÚ˛à)¨No free Connect Control     °dONLNdÚà˛⁄)ò
  885. Blocks (CCBs)°dONLNd˛
  886. (&    available°dONLNd
  887. D`(2b-8133°dONLNd#
  888. –)¨.PostScript error occurred during transmission °dONLNdQ
  889. –⁄)‡of°dONLNdT"Ã(>0data to printer.  Most often caused by a bug in °dONLNdÑÃ"⁄)‹the°dONLNdà".ò(J!PostScript code being downloaded.°dONLNd´.D:`(Vb-8132°dONLNd≤.:L)¨Timeout occurred. °dONLNdƒ.L:⁄)\ This error is returned when°dONLNd·:F1(b no data has °dONLNdÌ:1F⁄)A been sent to the printer for two°dONLNdFRS(nminutes.  Usually °dONLNd FSR⁄)ccaused by extremely long°dONLNd9R^1(z
  890. imaging time.°dONLNdH^Dj`(Üb-8131°dONLNdO^j)¨Printer °dONLNdW^j⁄)#(not responding:  it may have been turned°dONLNdÄjv-(í
  891. “off.”  This °dONLNdçj-v⁄)=$error occurs if a user turns off the°dONLNd≤vǨ(û)LaserWriter in the middle of a print job. °X°˘°dONLNd‹êú¡(∏6%The following errors are specific to °dONLNdè¡õ)©    PrGeneral°dONLNd
  892. êú)?:°dONLNd
  893. ™Z∂`(“x1°dONLNd©Ñµ√)*    NoSuchRsl°dONLNd™∂¢)l%Requested resolution is not supported «X«Ÿ°dONLNd@∑Z√`(flx2°dONLNdB∂Ѭ√)*    OpNotImpl
  894. °dONLNdL∑√.)l
  895. Requested  °dONLNdV∂.¬m)>    PrGeneral°dONLNd_∑m√∫)?  opcode not°dONLNdk√œ≤(Î*implemented in the current printer driver.°dONLNdó–J‹`(¯h-192°dONLNdúœÑ€—): resNotfound°dONLNd®–‹É)l The current printer driver does °dONLNd»–É‹∫)ì not support°dONLNd‘‹Ë/(    PrGeneral°dONLNd››/È3)?. XŸ°dONLNdfl±(*6TThe most common error encountered is -4101, which is generated if no LaserWriter is °dONLNd3±⁄(*œ    selected.°dONLNd>|(66Since this error is so °dONLNdU|⁄)dHcommon, it is a good idea to display a dialog box requesting the user to°dONLNdû&H(B6Aselect a printer from the Chooser when this error is encountered.°dONLNd‡JVÇ*0Further Reference: u4u˘°dONLNdÛW*c.+
  896. •°dONLNdıW<cç)Inside Macintosh°dONLNdWçcu)Q-, Volume II-145 & V-410, The Printing Manager°dONLNd3c*o.(ãH•°dONLNd5c<o˛)$Technical Note M.IM.DevIndPrinting —°dONLNd\o`{Í+$  Device-Independent Printing°dONLNdy{*á.(£H•°dONLNd{{<ás)
  897. d e v e l o p°dONLNdà{sá-)7&, July 1990, Issue 3, “Meet PrGeneral” ∂4∂˘
  898. (Œ612)
  899.  of 12(ŒZ#PR 10 - A Printing Loop That Cares…+YM.PR.PrintLoopˇ